package com.zts.modules.sys.service.impl;

import com.google.common.base.Strings;
import com.zts.base.exception.InternalServerErrorException;
import com.zts.base.exception.InvalidArgumentException;
import com.zts.base.exception.ServiceException;
import com.zts.base.exception.SourceNotFoundException;
import com.zts.base.page.PageBound;
import com.zts.common.Constant;
import com.zts.modules.sys.entity.Group;
import com.zts.modules.sys.entity.Role;
import com.zts.modules.sys.entity.User;
import com.zts.modules.sys.mapper.GroupMapper;
import com.zts.modules.sys.service.GroupService;
import com.zts.modules.sys.service.RoleService;
import com.zts.modules.sys.service.UserService;
import com.zts.util.BeanUtil;
import com.zts.util.BeanValidatorsUtil;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * Created by lily on 2017/6/7.
 */
@Service
public class GroupServiceImpl implements GroupService {
    @Autowired
    GroupMapper groupMapper;

    @Autowired
    UserService userService;

    @Autowired
    RoleService roleService;

    @Override
    public Group get(Long id) {
        if (null == id || id <= 0) {
            throw new InvalidArgumentException("参数<id>为空");
        }
        Group group = groupMapper.get(id);
        if (null == group) {
            throw new SourceNotFoundException("id[" + id + "]对应的组未找到！");
        }
        return group;
    }

    /**
     * 根据关键字查询
     *
     * @param entity
     * @return
     */
    @Override
    public List<Group> getByEntity(Group entity) {
        if (null == entity) {
            throw new InvalidArgumentException("参数为空");
        }
        if ((null == entity.getId() || entity.getId() < 0) && Strings.isNullOrEmpty(entity.getGroupName())) {
            throw new InvalidArgumentException("主键id和组名称不能同时为空");
        }
        List<Group> groupList = groupMapper.getByEntity(entity);
        if (null == groupList || groupList.size() == 0) {
            throw new SourceNotFoundException("对应的组未找到！");
        }
        return groupList;
    }

    @Override
    public List<Group> getByCondition(Map<String, Object> conditions) {
        return null;
    }

    @Override
    public List<Group> getList(Group entity, PageBound pageBound) {
        if (null == entity) {
            entity = new Group();
        }
        return groupMapper.getList(entity, pageBound);
    }

    @Override
    @Transactional
    public Group insert(Group entity) {
        if (null == entity) {
            throw new InvalidArgumentException("参数为空");
        }
        //先对entity进行校验
        BeanValidatorsUtil.validateWithException(entity);
        //校验通过后执行新增操作
        int i = groupMapper.insert(entity);
        if (i < 0 || null == entity.getId()) {
            throw new InternalServerErrorException("新增失败");
        }
        return groupMapper.get(entity.getId());
    }

    @Override
    @Transactional
    public int update(Group entity) {
        if (null == entity) {
            throw new InvalidArgumentException("参数为空");
        }
        if (null == entity.getId() || entity.getId() <= 0) {
            throw new InvalidArgumentException("参数对象id为空");
        }
        Group old = groupMapper.get(entity.getId());
        BeanUtils.copyProperties(entity, old, BeanUtil.getNullPropertyNames(entity));
        BeanValidatorsUtil.validateWithException(old);
        return groupMapper.update(old);
    }

    /**
     * 删除组
     *
     * @param entity
     * @return
     */
    @Override
    @Transactional
    public int delete(Group entity) {
        if (null == entity) {
            throw new InvalidArgumentException("参数为空");
        }
        if (null == entity.getId() || entity.getId() <= 0) {
            throw new InvalidArgumentException("参数对象id为空");
        }
        //先检查是否存在下级
        List<Group> children = getChildren(entity.getId(), "true");
        if (null != children && children.size() > 0) {
            throw new ServiceException("当前组存在下级组，不允许删除");
        }
        //检查是否存在用户
        List<User> users = getUsers(entity.getId(), "true");
        if (null != users && users.size() > 0) {
            throw new ServiceException("当前组下存在用户，不允许删除");
        }
        return groupMapper.delete(entity);
    }

    @Override
    public Group save(Group entity) {
        if (null == entity) {
            throw new IllegalArgumentException("参数为空");
        }
        if (null == entity.getId() || entity.getId() < 0) {
            return insert(entity);
        } else {
            update(entity);
            return get(entity.getId());
        }
    }

    /**
     * 获取下级组
     *
     * @param id
     * @param ifDirect 空或true:获取直接下级组，false：获取包括简介下级组在内的所有下级组
     * @return
     */
    public List<Group> getChildren(Long id, String ifDirect) {
        if (null == id || id < 0) {
            throw new InvalidArgumentException("参数<id>为空");
        }
        //若ifDirect为空，默认为true
        if (Strings.isNullOrEmpty(ifDirect)) {
            ifDirect = "true";
        }
        return groupMapper.getChildren(id, ifDirect);
    }

    /**
     * 获取组下的用户
     *
     * @param groupId
     * @param ifDirect 空或true:获取当前组的直接用户，false：获取包括简介下级组在内的所有下级组的所有用户
     * @return
     */
    public List<User> getUsers(Long groupId, String ifDirect) {
        if (null == groupId || groupId < 0) {
            throw new InvalidArgumentException("参数<groupId>为空");
        }
        //若ifDirect为空，默认为true
        if (Strings.isNullOrEmpty(ifDirect)) {
            ifDirect = "true";
        }
        return groupMapper.getUsers(groupId, ifDirect);
    }


    /**
     * 将某个用户加入某个组中
     *
     * @param userId
     * @param groupId
     * @param groupType 1:所属部门,2：兼职部门
     * @param sortNum
     * @return
     */
    @Transactional
    public int addUserIntoGroup(Long userId, Long groupId, String groupType,int sortNum) {
        if (null == userId || userId < 0) {
            throw new IllegalArgumentException("参数<userId>为空");
        }
        if (null == groupId || groupId < 0) {
            throw new IllegalArgumentException("参数<groupId>为空");
        }
        if (Strings.isNullOrEmpty(groupType)) {
            throw new IllegalArgumentException("参数<groupType>为空");
        }
        if (!"1".equals(groupType) && !"2".equals(groupType)) {
            throw new IllegalArgumentException("参数<groupType>不合法！");
        }
        if(sortNum < 0){
            throw new IllegalArgumentException("参数<sortNum>不合法！");
        }
        //校验group是否存在和有效
        Group group = get(groupId);
        if (null == group) {
            throw new SourceNotFoundException("id[" + groupId + "]对应的组不存在！");
        }
        if (!"1".equals(group.getStatus())) {
            throw new InvalidArgumentException("id[" + groupId + "]对应的组状态无效");
        }
        //校验用户是否存在和有效
        if (!userService.checkStatus(userId)) {
            throw new InvalidArgumentException("id[" + userId + "]对应的用户状态无效!");
        }
        return groupMapper.addUserIntoGroup(userId, groupId, groupType,sortNum);
    }

    /**
     * 批量将多个用户加入某个组中
     *
     * @param userIds
     * @param groupId
     * @param groupType 1:所属部门,2：兼职部门
     * @return
     */
    @Transactional
    public int addUsersIntoGroup(List<Long> userIds, Long groupId, String groupType) {
        if (null == userIds || userIds.size() <= 0) {
            throw new IllegalArgumentException("参数<userIds>为空");
        }
        if (null == groupId || groupId < 0) {
            throw new IllegalArgumentException("参数<groupId>为空");
        }
        if (Strings.isNullOrEmpty(groupType)) {
            throw new IllegalArgumentException("参数<groupType>为空");
        }
        if (!"1".equals(groupType) && !"2".equals(groupType)) {
            throw new IllegalArgumentException("参数<groupType>不合法！");
        }

        //校验group是否存在和有效
        Group group = get(groupId);
        if (null == group) {
            throw new SourceNotFoundException("id[" + groupId + "]对应的组不存在！");
        }
        if (!Constant.STATUS_VALID.equals(group.getStatus())) {
            throw new InvalidArgumentException("id[" + groupId + "]对应的组状态无效");
        }
        //校验用户是否存在和有效
        for (int i = 0; i < userIds.size(); i++) {
            if (!userService.checkStatus(userIds.get(i)))
                throw new InvalidArgumentException("id[" + userIds.get(i) + "]对应的用户状态无效!");
        }
        return groupMapper.addUsersIntoGroup(userIds, groupId, groupType);
    }

    /**
     * 将某个用户从某个组中删除
     *
     * @param userId
     * @param groupId
     * @return
     */
    @Transactional
    public int deleteUserFromGroup(Long userId, Long groupId) {
        if (null == userId || userId < 0) {
            throw new IllegalArgumentException("参数<userId>为空");
        }
        if (null == groupId || groupId < 0) {
            throw new IllegalArgumentException("参数<groupId>为空");
        }
        //校验用户是否在当前组中
        if (!checkUserGroupExist(userId, groupId, "true")) {
            throw new SourceNotFoundException("用户[" + userId + "]目前不在组[" + groupId + "]中");
        }
        //若当前用户没有该组的授权，需要先删除这些状态为“撤销授权”的记录
        roleService.deleteRoleByUserAndGroup(userId, groupId);
        //删除用户与组的对应关系
        return groupMapper.deleteUserFromGroup(userId, groupId);
    }

    /**
     * 批量将多个用户从某个组中删除
     *
     * @param userIds
     * @param groupId
     * @return
     */
    @Transactional
    public int deleteUsersFromGroup(List<Long> userIds, Long groupId) {
        if (null == userIds || userIds.size() <= 0) {
            throw new IllegalArgumentException("参数<userIds>为空");
        }
        if (null == groupId || groupId < 0) {
            throw new IllegalArgumentException("参数<groupId>为空");
        }
        //遍历校验用户是否在当前组中
        for (int i = 0; i < userIds.size(); i++) {
            Long tmp_userId = userIds.get(i);
            if (!checkUserGroupExist(tmp_userId, groupId, "true"))
                throw new SourceNotFoundException("用户[" + tmp_userId + "]目前不在组[" + groupId + "]中");
        }
        //若当前用户没有该组的授权，需要先删除这些状态为“撤销授权”的记录
        roleService.deleteRoleByUsersAndGroup(userIds, groupId);
        //删除用户与组的对应关系
        return groupMapper.deleteUsersFromGroup(userIds, groupId);
    }

    /**
     * 是否存在
     *
     * @param id
     * @return
     */
    public boolean checkExist(Long id) {
        if (null == id || id < 0) {
            throw new IllegalArgumentException("参数<id>为空");
        }

        Group group = get(id);
        //group为空，则不存在
        if (null == group) {
            return false;
        }
        return true;
    }

    /**
     * 状态是否有效
     *
     * @param id
     * @return
     */
    public boolean checkStatus(Long id) {
        if (null == id || id < 0) {
            throw new IllegalArgumentException("参数<id>为空");
        }
        Group group = get(id);
        //group为空，则不存在
        if (null == group) {
            throw new SourceNotFoundException("id[" + id + "]对应的组不存在！");
        }
        //status ：1有效 见group类说明
        if (!"1".equals(group.getStatus())) {
            return false;
        }

        return true;
    }

    /**
     * 用户是否在组中
     *
     * @param userId
     * @param groupId
     * @param ifDirect 空或true：只校验直接关系  false：校验用户是否是该组的递归下级组
     * @return
     */
    public boolean checkUserGroupExist(Long userId, Long groupId, String ifDirect) {
        if (null == userId || userId < 0) {
            throw new IllegalArgumentException("参数<userId>为空");
        }
        if (null == groupId || groupId < 0) {
            throw new IllegalArgumentException("参数<groupId>为空");
        }
        if (Strings.isNullOrEmpty(ifDirect)) {
            ifDirect = "true";//默认值校验直接关系
        }
        if ("true".equals(ifDirect)) {
            return groupMapper.checkUserGroupExist(userId, groupId);
        } else {
            //获取当前group的所有用户（包括间接下级）
            List<User> userList = getUsers(groupId, "false");
            //userList转换为userIdList
            List<Long> userIdList = new ArrayList<>();
            if (null != userList && userList.size() > 0) {
                for (int i = 0; i < userList.size(); i++) {
                    userIdList.add((userList.get(i)).getId());
                }
            }
            //若包含在userIdList中，则返回true
            if (userIdList.contains(userId)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 给组授权，组下某些用户除外
     *
     * @param groupId
     * @param roleId
     * @param userIds
     * @return
     */
    public int groupGrantExcludeUsers(Long groupId, Long roleId, List<Long> userIds) {
        return roleService.groupGrantExcludeUsers(groupId, roleId, userIds);
    }

    /**
     * 组批量授权
     *
     * @param groupId
     * @param roleIds
     * @param grantType
     * @return
     */
    public int batchGrant(Long groupId, List<Long> roleIds, String grantType) {
        return roleService.batchGrant(groupId, "1", roleIds, grantType);
    }

    /**
     * 组删除单一角色
     *
     * @param groupId
     * @param roleId
     * @param grantType
     * @return
     */
    public int singleGrantDelete(Long groupId, Long roleId, String grantType) {
        return roleService.singleGrantDelete(groupId, Constant.GRANT_OBJECT_GROUP, roleId, grantType);
    }

    /**
     * 组批量删除多个角色
     *
     * @param groupId
     * @param roleIds
     * @param grantType
     * @return
     */
    public int batchGrantDelete(Long groupId, List<Long> roleIds, String grantType) {
        return roleService.batchGrantDelete(groupId, Constant.GRANT_OBJECT_GROUP, roleIds, grantType);
    }

    /**
     * 查看组直接拥有的角色
     *
     * @param groupId
     * @return
     */
    public List<Role> getRoles(Long groupId) {
        List<Role> roleList = roleService.getRolesByGroupId(groupId);
        if (null == roleList || roleList.size() <= 0) {
            throw new SourceNotFoundException("组[" + groupId + "]尚未分配角色！");
        }
        return roleList;
    }

    /**
     * 查看组拥有的所有角色，包括组（group)的递归上级组拥有的角色
     *
     * @param groupId
     * @return
     */
    public List<Role> getAllRoles(Long groupId) {
        List<Role> roleList = roleService.getAllRolesByGroupId(groupId);
        if (null == roleList || roleList.size() <= 0) {
            throw new SourceNotFoundException("组[" + groupId + "]尚未分配角色！");
        }
        return roleList;
    }

}
